/**
 * @file 跟踪窗口实现
 *
 * 跟踪窗口实现
 *
 * @author wq1977@gmail.com
 */

 
#include <wx/datetime.h>
#include <wx/splitter.h>

#include <wx/tokenzr.h>
#include "mycanvas.h"
#include "TraceForm.h"
#include "ScenariosForm.h"

DEFINE_EVENT_TYPE(wxEVT_COMMAND_TRACE_FORM)
IMPLEMENT_DYNAMIC_CLASS(wxTraceFormEvent, wxNotifyEvent)

BEGIN_EVENT_TABLE(TraceForm, wxMDIChildFrame)
    EVT_TRACE_FORM(-1,TraceForm::OnTraceForm)
    EVT_CLOSE(TraceForm::OnClose)
END_EVENT_TABLE()

void TraceForm::OnTraceForm(wxTraceFormEvent& event)
{
    int Level=event.GetLevel();
    switch (Level){
    case TL_MESSAGE:
    m_Text->SetDefaultStyle(wxTextAttr(*wxBLUE));
    break;
    case TL_WARNING:
    m_Text->SetDefaultStyle(wxTextAttr(*wxCYAN));
    break;
    case TL_MATCH_RULE:
    m_Text->SetDefaultStyle(wxTextAttr(*wxGREEN));
    break;
    case TL_MESSAGE_RETRANS:
    m_Text->SetDefaultStyle(wxTextAttr(*wxLIGHT_GREY));
    break;
    default:
    m_Text->SetDefaultStyle(wxTextAttr(*wxRED));
    break;
    }
    wxDateTime now = event.GetWhen();

    m_Text->AppendText(wxString::Format(wxT("(%04d-%02d-%02d %02d:%02d:%02d %03d) "),
                      now.GetYear(),
                      now.GetMonth(),
                      now.GetDay(),
                      now.GetHour(),
                      now.GetMinute(),
                      now.GetSecond(),
                      now.GetMillisecond()));

    m_Text->SetDefaultStyle(wxTextAttr(*wxBLACK));

    wxString slog=event.GetLogStr();

    if(TL_SIP_MESSAGE != Level)
    {
        m_Text->AppendText(slog+wxT("\n"));
        return;
    }

    /*[%d,%s,%d,%s]-----收发，消息名，长度，地址*/
    wxString sName1,sName2;
    sName1 = slog.BeforeFirst(']');
    sName2 = sName1.AfterFirst('[');

    wxStringTokenizer xST(sName2,wxT( "," ),wxTOKEN_STRTOK);

    //assert(xST.CountTokens() =4);

    wxString sDir=xST.GetNextToken();
    wxString sAddr=xST.GetNextToken();
    wxString sName=xST.GetNextToken();
    wxString sLen=xST.GetNextToken();

    wxString sMsgDesc=wxString::Format(_("[Recv message:%s from %s ,length is %s]"),sAddr.c_str(),sName.c_str(),sLen.c_str());
    if(!sDir.CmpNoCase(wxT("1")))
        sMsgDesc = wxString::Format(_("[Send message:%s to %s,length is %s]"),sName.c_str(),sAddr.c_str(),sLen.c_str());

    m_Text->AppendText(sMsgDesc+wxT("\n"));
    size_t from = m_Text->GetLastPosition();

    m_Text->AppendText(slog.AfterFirst('\n'));
	size_t to = m_Text->GetLastPosition();

    if(TL_SIP_MESSAGE != Level)
       return;

    MsgInfo *oMsginfo=new MsgInfo;

    oMsginfo->beginpos = from;
    oMsginfo->endpos = to;

    if(!sDir.CmpNoCase(wxT("1")))
    {
        oMsginfo->pt1 = m_msgflow->m_currentpos;
        oMsginfo->pt2.x = m_msgflow->m_currentpos.x+COLUMN_INTERVAL_LEN;
        oMsginfo->pt2.y = m_msgflow->m_currentpos.y+ROW_INTERVAL_LEN;

        //sName << wxString::Format(wxT("[%d,%d,%d,%d]"),from,to,oMsginfo->nlineno,m_msgflow->m_msgtext->XYToPosition(0,oMsginfo->nlineno));
        oMsginfo->sTxt = sName;

        m_msgflow->m_msglist.Append(oMsginfo);
        m_msgflow->Refresh();

        m_msgflow->m_currentpos = wxPoint(oMsginfo->pt1.x,oMsginfo->pt1.y+ROW_INTERVAL_LEN);
    }
    else
    {
        oMsginfo->pt1.x = m_msgflow->m_currentpos.x+COLUMN_INTERVAL_LEN;
        oMsginfo->pt1.y = m_msgflow->m_currentpos.y;
        oMsginfo->pt2.x = m_msgflow->m_currentpos.x;
        oMsginfo->pt2.y = m_msgflow->m_currentpos.y+ROW_INTERVAL_LEN;

        //sName << wxString::Format(wxT("[%d,%d,%d,%d]"),from,to,oMsginfo->nlineno,m_msgflow->m_msgtext->XYToPosition(0,oMsginfo->nlineno));
        oMsginfo->sTxt = sName;

        m_msgflow->m_msglist.Append(oMsginfo);
        m_msgflow->Refresh();

        m_msgflow->m_currentpos = oMsginfo->pt2;
    }
}

void TraceForm::Clear(){
    if(m_msgflow)
        m_msgflow->m_msglist.Clear();

    m_Text->Clear();
}

void TraceForm::OnClose(wxCloseEvent& event)
{
  ScenariosForm *p= (ScenariosForm *)TraceSrc;
  if ((p) && (p->IsInProgress()))
    {
      wxLogError(_("Scenarios Is still in progress!!"));
      event.Veto();
        return;
    }
  if (p){
    p->RemoveTracer(this);
  }
  event.Skip();
}

TraceForm::TraceForm(wxMDIParentFrame *parent, const wxString& title, const wxPoint& pos, const wxSize& size, const long style): wxMDIChildFrame(parent, -1, title, pos, size,
                         style | wxNO_FULL_REPAINT_ON_RESIZE)
{
    CreateStatusBar();

    wxSplitterWindow* osplitter = new wxSplitterWindow(this);
    osplitter->SetSashGravity(1);

    m_msgflow = new MyCanvas( osplitter, wxID_ANY, wxDefaultPosition, wxDefaultSize);

    m_Text = new wxTextCtrl(osplitter, -1,wxT(""),wxDefaultPosition,wxDefaultSize,
								wxTE_RICH |  wxTE_MULTILINE | wxTE_READONLY | wxVSCROLL);

    SetName(wxT("TRACEFORM"));

    m_msgflow->m_msgtext = m_Text;
    osplitter->SplitHorizontally(m_msgflow, m_Text, 100);
    m_Text->SetAutoLayout(TRUE);
}

void TraceForm::UpdateTitle(){
  wxString title=_("Trace Form for ");
  title+=wxString::Format(wxT(" %d:"),((ScenariosForm*)TraceSrc)->GetFormIndex()+1)+wxT(" ");
	for (size_t i=0;i<TraceTarget.size();i++){
		title += wxString::Format(wxT(" %d"),TraceTarget[i]);
	}	
	SetTitle(title);
}

bool TraceForm::IsTracingMe(int index){
	for (size_t i=0;i<TraceTarget.size();i++){
		if (TraceTarget[i] == index) return true;
	}
	return false;
}

void TraceForm::Trace(int Level,const wxString& Value, bool lock){
  wxTraceFormEvent event(Value,Level,wxEVT_COMMAND_TRACE_FORM, -1);
  event.SetEventObject(this);
  wxPostEvent(GetEventHandler(),event);
}

TraceForm::~TraceForm(){
  /*ScenariosForm *p= (ScenariosForm *)TraceSrc;
	if (p){
		p->RemoveTracer(this);
		}*/
}
